/*
 * Copyright 2008 Nordic Consulting & Development Company
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package pl.ncdc.web.login.client.ui;

import pl.ncdc.web.login.client.User;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;

/**
 * Widget showing list of user data. The list consist of
 * widgets produced by {@link UserWidgetFactory}.
 * <p>
 * Created on Apr 17, 2008
 *
 * @author hshsce
 * @version $Id: UserListWidget.java 42 2008-04-18 11:14:40Z leszekgruchala $
 */
public class UserListWidget extends Composite {

	public static final String WIDGET_ID = "ncdc-web-login-UserListWidget";

	public interface Style {

		String EVEN_ROW = "EvenRow";

		String ODD_ROW = "OddRow";

		String SELECTED = "Selected";

	}

	private UserWidgetFactory m_factory;

	private final ScrollPanel m_scrollPanel = new ScrollPanel();

	private UserData m_userData;

	private UserSelectionListenerCollection m_listeners;

	private boolean m_enabled = true;

	public UserListWidget() {
		this(new User[0]);
	}

	public UserListWidget(final User[] users) {
		this(users, new DefaultUserWidgetFactory("images/users"));
	}

	public UserListWidget(final UserWidgetFactory factory) {
		this(new User[0], factory);
	}

	/**
	 * 
	 * @param users
	 * @param factory
	 * @throws IllegalArgumentException if the <code>users</code> or <code>factory</code>
	 * 			is <code>null</code>.
	 */
	public UserListWidget(final User[] users, final UserWidgetFactory factory) {
		setUsers(users);
		setUserWidgetFactory(factory);
		initWidget(m_scrollPanel);
		setStyleName(WIDGET_ID);
	}

	public void setUsers(final User[] users) {
		if (users == null) {
			throw new IllegalArgumentException("users cannot be null");
		}
		final UserData data = new UserData(users);
		final Grid grid = data.m_grid;
		final RowFormatter rowFormatter = data.m_grid.getRowFormatter();
		for (int row = 0; row < users.length; row++) {
			final User user = users[row];
			final Widget widget = m_factory.newWidget(user);
			grid.setWidget(row, 0, widget);
			final String rowStyle;
			if ((row % 2) == 0) {
				rowStyle = Style.EVEN_ROW;
			} else {
				rowStyle = Style.ODD_ROW;
			}
			rowFormatter.setStyleName(row, rowStyle);
		}
		grid.addTableListener(new TableListener() {
			public void onCellClicked(final SourcesTableEvents sender, final int row, final int cell) {
				if (m_enabled) {
					final String uid = users[row].getUid();
					data.selectUserWidget(uid);
					m_listeners.fireUserSelected(uid);					
				}
			}
		});
		m_userData = data;
		m_scrollPanel.setWidget(data.m_grid);
	}

	public void setUserWidgetFactory(final UserWidgetFactory factory) {
		if (factory == null) {
			throw new IllegalArgumentException("factory cannot be null");
		}
		m_factory = factory;
	}

	public void selectUser(final String uid) {
		final Widget userWidget = m_userData.selectUserWidget(uid);
		if (userWidget != null) {
			//TODO does not work in opera - probably in other browsers too, in firefox OK
			DOM.scrollIntoView(userWidget.getElement());
		}
	}

	public String getSelectedUid() {
		return m_userData.getSelectedUid();
	}

	public void addUserSelectionListener(final UserSelectionListener listener) {
		if (m_listeners == null) {
			m_listeners = new UserSelectionListenerCollection();
		}
		m_listeners.add(listener);
	}

	public void removeUserSelectionListener(final UserSelectionListener listener) {
		if (m_listeners != null) {
			m_listeners.remove(listener);
		}
	}

	/**
	 * Sets whether this widget is enabled. Disabling this widget
	 * means inability to choose any user.
	 * 
	 * @param enabled <code>true</code> to enable the widget, <code>false</code>
	 *			to disable it
	 */
	public void setEnabled(boolean enabled) {
		m_enabled = enabled;
	}

	public boolean isEnabled() {
		return m_enabled;
	}

	private static class UserData {
		private final User[] m_users;
		private final Grid m_grid;
		private int m_selectedRow = -1;
		private UserData(final User[] users) {
			m_users = users;
			m_grid = new Grid(users.length, 1);
			m_grid.setCellPadding(0);
			m_grid.setCellSpacing(0);
		}
		private String getSelectedUid() {
			final String uid;
			if (m_selectedRow >= 0) {
				uid = m_users[m_selectedRow].getUid();
			} else {
				uid = null;
			}
			return uid;
		}
		private Widget selectUserWidget(final String uid) {
			final RowFormatter formatter = m_grid.getRowFormatter();
			if (m_selectedRow >= 0) {
				formatter.removeStyleName(m_selectedRow, Style.SELECTED);
				m_selectedRow = -1;
			}
			for (int row = 0; row < m_users.length; row++) {
				if (m_users[row].getUid().equals(uid)) {
					formatter.addStyleName(row, Style.SELECTED);
					m_selectedRow = row;
					return m_grid.getWidget(row, 0);
				}
			}
			return null;
		}
	}

}
